
package com.gcloud.mesh.analysis.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.PostConstruct;

import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.ParamException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.gcloud.framework.db.PageResult;
import com.gcloud.mesh.analysis.arima.ARIMAManager;
import com.gcloud.mesh.analysis.dao.SubhealthAlertDao;
import com.gcloud.mesh.analysis.dao.SubhealthInfoDao;
import com.gcloud.mesh.analysis.dao.SubhealthThresholdDao;
import com.gcloud.mesh.analysis.entity.SubhealthAlertEntity;
import com.gcloud.mesh.analysis.entity.SubhealthInfoEntity;
import com.gcloud.mesh.analysis.entity.SubhealthThresholdEntity;
import com.gcloud.mesh.analysis.service.IDataCleaningService;
import com.gcloud.mesh.asset.enums.DeviceType;
import com.gcloud.mesh.asset.service.IAssetService;
import com.gcloud.mesh.header.enums.SubhealthAlertLevelType;
import com.gcloud.mesh.header.enums.SubhealthDeviceType;
import com.gcloud.mesh.header.enums.SubhealthThresholdMeter;
import com.gcloud.mesh.header.exception.AnalysisErrorCode;
import com.gcloud.mesh.header.exception.BaseException;
import com.gcloud.mesh.header.exception.SubhealthErrorCode;
import com.gcloud.mesh.header.msg.analysis.AlertStatisticMsg;
import com.gcloud.mesh.header.msg.analysis.CountAlertsMsg;
import com.gcloud.mesh.header.msg.analysis.ListDatacenterSubhealthMsg;
import com.gcloud.mesh.header.msg.analysis.ListSubhealthThresholdMsg;
import com.gcloud.mesh.header.msg.analysis.ListThresholdMeterMsg;
import com.gcloud.mesh.header.msg.analysis.PageAirSubhealthMsg;
import com.gcloud.mesh.header.msg.analysis.PageAlertMsg;
import com.gcloud.mesh.header.msg.analysis.PageDatacenterSubhealthMsg;
import com.gcloud.mesh.header.msg.analysis.PageUpsSubhealthMsg;
import com.gcloud.mesh.header.msg.analysis.SetSubhealthThresholdMsg;
import com.gcloud.mesh.header.msg.asset.ListDatacenterMsg;
import com.gcloud.mesh.header.msg.asset.ListDeviceMsg;
import com.gcloud.mesh.header.vo.analysis.AlertLevelVo;
import com.gcloud.mesh.header.vo.analysis.AlertStatisticVo;
import com.gcloud.mesh.header.vo.analysis.SubhealthAirVo;
import com.gcloud.mesh.header.vo.analysis.SubhealthAlertCountPageVo;
import com.gcloud.mesh.header.vo.analysis.SubhealthAlertVo;
import com.gcloud.mesh.header.vo.analysis.SubhealthDatacenterVo;
import com.gcloud.mesh.header.vo.analysis.SubhealthDeviceThresholdVo;
import com.gcloud.mesh.header.vo.analysis.SubhealthUpsVo;
import com.gcloud.mesh.header.vo.analysis.ThresholdMeterVo;
import com.gcloud.mesh.header.vo.asset.DatacenterItemVo;
import com.gcloud.mesh.header.vo.asset.DeviceItemVo;
import com.gcloud.mesh.header.vo.monitor.SampleVo;
import com.gcloud.mesh.monitor.service.StatisticsCheatService;
import com.gcloud.mesh.monitor.service.StatisticsService;
import com.gcloud.mesh.utils.MeshMathUtil;
import com.gcloud.mesh.utils.TimestampUtil;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class SubhealthThresholdService {

	public static final String TEMPLATE = "预警数量";

	@Autowired
	private SubhealthThresholdDao tsDao;

	@Autowired
	private SubhealthInfoDao infoDao;

	@Autowired
	private SubhealthAlertDao alertDao;

	@Autowired
	private IAssetService assetService;

	@Autowired
	private StatisticsService statsService;

	@Autowired
	private StatisticsCheatService statsCheatService;

	@Autowired
	private IDataCleaningService dataCleaningService;
	
	@Autowired
	private ARIMAManager arimaManager;

	private static final Map<String, List<SubhealthDeviceThresholdVo>> THRESHOLDS = new HashMap<>();

	@PostConstruct
	public void init() throws Exception {
		initSubhealthThreshold();
		updateCache();
	}

	private void updateCache() {
		List<SubhealthDeviceThresholdVo> thresholds = this.tsDao.list(SubhealthDeviceThresholdVo.class);
		Map<String, List<SubhealthDeviceThresholdVo>> threshMap = thresholds.stream()
				.collect(Collectors.groupingBy(s -> s.getType()));
		for (Entry<String, List<SubhealthDeviceThresholdVo>> entry : threshMap.entrySet()) {
			THRESHOLDS.put(entry.getKey(), entry.getValue());
		}
	}

	@Scheduled(initialDelay = 30 * 1000, fixedDelay = 60 * 1000)
	void periodCheckSubhealth() {
		log.info("[Subhealth] period check subhealth");
		for (Entry<String, List<SubhealthDeviceThresholdVo>> entry : THRESHOLDS.entrySet()) {
			SubhealthDeviceType type = SubhealthDeviceType.getByName(entry.getKey().toUpperCase());
			checkSubhealth(type, entry.getValue());
		}
	}

	// private void checkSubhealth(List<SubhealthDeviceThresholdVo> thresholds)
	// {
	// ListDeviceMsg deviceMsg = new ListDeviceMsg();
	// List<DeviceItemVo> devices = assetService.listDevice(deviceMsg);
	// ListDatacenterMsg dcMsg = new ListDatacenterMsg();
	// List<DatacenterItemVo> datacenters = assetService.listDatacenter(dcMsg);
	// for (SubhealthDeviceThresholdVo vo : thresholds) {
	// if
	// (SubhealthDeviceType.DATACENTER.equals(SubhealthDeviceType.getByName(vo.getType().toUpperCase())
	// != null)) {
	// // 机房亚健康检查
	// checkDatacenterSubhealth(vo, datacenters);
	// } else {
	// // 设备亚健康检查
	// checkDeviceSubhealth(vo, devices);
	// }
	// }
	// }

	private void checkSubhealth(SubhealthDeviceType type, List<SubhealthDeviceThresholdVo> thresholds) {

		for (SubhealthDeviceThresholdVo vo : thresholds) {
			if (SubhealthDeviceType.DATACENTER.equals(type)) {
				// 机房亚健康检查
				// checkDatacenterSubhealth(vo);
				checkDatacenterSubhealth(type, thresholds);
			} else {
				// 设备亚健康检查
				// checkDeviceSubhealth(vo);
				checkDeviceSubhealth(type, thresholds);
			}
		}
	}

	private void updateSubhealthStatus(SubhealthDeviceThresholdVo vo, String resourceId) {

		SubhealthInfoEntity e = this.infoDao.getById(resourceId);
		if (e == null) {
			e = new SubhealthInfoEntity();
			e.setId(resourceId);
			e.setDeviceType(vo.getType());
			e.setSubhealth(true);
			this.infoDao.save(e);
		} else {
			e.setSubhealth(true);
			this.infoDao.update(e);
		}
	}

	private void saveAlert(SubhealthDeviceThresholdVo vo, String resourceId, String name, String content,
			String level) {

		SubhealthAlertEntity ae = new SubhealthAlertEntity();
		ae.setId(UUID.randomUUID().toString());
		ae.setDeviceType(vo.getType());
		ae.setMeter(vo.getMeter());
		ae.setMeterName(SubhealthThresholdMeter.getByMeter(vo.getMeter()).getCnName());
		ae.setResourceId(resourceId);
		ae.setResourceName(name);
		ae.setContent(content);
		ae.setLevel(level);
		ae.setCreateTime(new Date());

		// try {
		// DeviceItemVo device = assetService.detailDevice(vo.getResourceId(),
		// null);
		// ae.setResourceName(device.getName());
		// } catch (Exception e) {
		// log.info("[SubhealthThresholdService][checkDatacenterSubhealth]
		// AssetService的detailDevice方法访问异常: {}", e.getMessage());
		// }
		try {
			alertDao.save(ae);
		} catch (Exception e) {
			log.info("[SubhealthThresholdService][saveAlert] 数据库保存失败: {}", e.getMessage());
		}

	}

	// private void checkDatacenterSubhealth() {
	//
	// ListDatacenterMsg msg = new ListDatacenterMsg();
	// List<DatacenterItemVo> datacenters = assetService.listDatacenter(msg);
	// for (DatacenterItemVo datacenter : datacenters) {
	// try {
	// checkDatacenterSubhealth(datacenter.getId());
	// } catch (Exception e) {
	//
	// }
	// }
	//
	// }

	// private void checkDatacenterSubhealth(String datacenterId) {
	// ListDeviceMsg msg = new ListDeviceMsg();
	// msg.setDatacenterId(datacenterId);
	// List<DeviceItemVo> devices = null;
	// try {
	// devices = assetService.listDevice(msg);
	// } catch (Exception e) {
	// log.info("[SubhealthThresholdService][checkDatacenterSubhealth]
	// checkDatacenterSubhealth执行失败, AssetService的listDevice方法访问异常: {}",
	// e.getMessage());
	// }
	// if (devices != null) {
	// List<SubhealthInfoEntity> subhealthInfos = infoDao.findAll();
	// Map<String, Boolean> subhealthInfoMap = subhealthInfos.stream().filter(s
	// -> SubhealthDeviceType.get(s.getDeviceType()) !=
	// SubhealthDeviceType.DATACENTER).collect(Collectors.toMap(SubhealthInfoEntity::getId,
	// SubhealthInfoEntity::getSubhealth));
	// for (DeviceItemVo device : devices) {
	// DeviceType type = DeviceType.getDeviceTypeByNo(device.getType());
	// if (type != DeviceType.AIR_CONDITION && type != DeviceType.UPS) {
	// continue;
	// }
	// String key = device.getId();
	// if (subhealthInfoMap.get(key) != null && subhealthInfoMap.get(key) ==
	// true) {
	// SubhealthInfoEntity info = infoDao.getById(datacenterId);
	// if (info == null) {
	// info = new SubhealthInfoEntity();
	// info.setId(datacenterId);
	// info.setDeviceType(SubhealthDeviceType.DATACENTER.name());
	// info.setSubhealth(true);
	// infoDao.save(info);
	// } else if (info.getSubhealth() == false) {
	// info.setSubhealth(true);
	// infoDao.update(info);
	// }
	// break;
	// }
	// }
	// }
	//
	// }

	private double getMeterValue(String meter, String resourceId) {
		double res = 0;
		try {
			List<SampleVo> values = this.statsCheatService.latestSamples(meter, resourceId);
//			res = values.get(0).getVolume().doubleValue();
			res = predictTimeSeries(values.get(0).getVolume());
		} catch (Exception e) {
			log.info("[SubhealthThresholdService][getMeterValue] StatisticsService的latestSamples方法访问异常: {}",
					e.getMessage());
		}
		return res;
	}

	public Integer countAlerts(CountAlertsMsg msg) {
		SubhealthDeviceType d = SubhealthDeviceType.checkAndGet(msg.getDeviceType());
		return this.alertDao.count(d.name());
	}

	public List<AlertStatisticVo> alertStatistic(AlertStatisticMsg msg) {
		List<AlertStatisticVo> statistic = new ArrayList<AlertStatisticVo>();
		String template = "预警数量";
		for (SubhealthDeviceType type : SubhealthDeviceType.values()) {
			AlertStatisticVo vo = new AlertStatisticVo();
			vo.setName(SubhealthDeviceType.getByName(type.getName()).getCnName() + template);
			vo.setType(SubhealthDeviceType.getByName(type.getName()).getName());
			vo.setValue(alertDao.count(type.name()));
			statistic.add(vo);
		}
		return statistic;
	}

	public PageResult<SubhealthAlertVo> pageAlert(PageAlertMsg msg) {
		if (msg.getDeviceType() != null) {
			SubhealthDeviceType type = SubhealthDeviceType.getByName(msg.getDeviceType());
			if (type == null) {
				throw new ParamException(AnalysisErrorCode.DEVICETYPE_NOT_FOUND);
			}
		}
		if (msg.getMeter() != null) {
			SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(msg.getMeter());
			if (meter == null) {
				throw new ParamException(AnalysisErrorCode.METER_NOT_FOUND);
			}
		}
		if (msg.getLevel() != null) {
			SubhealthAlertLevelType level = SubhealthAlertLevelType.getByName(msg.getLevel());
			if (level == null) {
				throw new ParamException(AnalysisErrorCode.LEVEL_NOT_FOUND);
			}
		}

		PageResult<SubhealthAlertVo> result = this.alertDao.page(msg.getDeviceType(), msg.getMeter(), msg.getLevel(),
				TimestampUtil.dateToStr(msg.getStartTime()), TimestampUtil.dateToStr(msg.getEndTime()), msg.getPageNo(),
				msg.getPageSize(), SubhealthAlertVo.class);
		for (SubhealthAlertVo vo : result.getList()) {
			List<SubhealthDeviceThresholdVo> thresholds = THRESHOLDS.get(vo.getDeviceType());
			SubhealthDeviceThresholdVo threshold = thresholds.stream().filter(s -> s.getMeter().equals(vo.getMeter()))
					.findFirst().orElse(null);
			if (threshold != null) {
				SubhealthAlertLevelType levelType = SubhealthAlertLevelType.getByName(vo.getLevel());
				SubhealthDeviceType deviceType = SubhealthDeviceType.getByName(vo.getDeviceType());
				if (levelType != null) {
					vo.setLevelCnName(levelType.getCnName());
				}
				if (deviceType != null) {
					vo.setDeviceTypeCnName(deviceType.getCnName());
				}

			}
		}
		return result;
	}

	public SubhealthAlertCountPageVo pageCountAndAlert(PageAlertMsg msg) {

		if (msg.getStartTime() != null && msg.getEndTime() != null) {
			if (msg.getStartTime().compareTo(msg.getEndTime()) >= 0) {
				throw new ParamException(null, "开始时间应早于结束时间");
			}
		}

		if (msg.getDeviceType() != null) {
			SubhealthDeviceType type = SubhealthDeviceType.getByName(msg.getDeviceType());
			if (type == null) {
				throw new ParamException(AnalysisErrorCode.DEVICETYPE_NOT_FOUND);
			}
		}
		if (msg.getMeter() != null) {
			SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(msg.getMeter());
			if (meter == null) {
				throw new ParamException(AnalysisErrorCode.METER_NOT_FOUND);
			}
		}
		if (msg.getLevel() != null) {
			SubhealthAlertLevelType level = SubhealthAlertLevelType.getByName(msg.getLevel());
			if (level == null) {
				throw new ParamException(AnalysisErrorCode.LEVEL_NOT_FOUND);
			}
		}
		SubhealthAlertCountPageVo res = new SubhealthAlertCountPageVo();

		PageResult<SubhealthAlertVo> result = this.alertDao.page(msg.getDeviceType(), msg.getMeter(), msg.getLevel(),
				TimestampUtil.dateToStr(msg.getStartTime()), TimestampUtil.dateToStr(msg.getEndTime()), msg.getPageNo(),
				msg.getPageSize(), SubhealthAlertVo.class);
		List<AlertStatisticVo> alertCounts = null;
		if (result != null) {
			for (SubhealthAlertVo vo : result.getList()) {
				SubhealthAlertLevelType levelType = SubhealthAlertLevelType.getByName(vo.getLevel());
				SubhealthDeviceType deviceType = SubhealthDeviceType.getByName(vo.getDeviceType());
				if (levelType != null) {
					vo.setLevelCnName(levelType.getCnName());
				}
				if (deviceType != null) {
					vo.setDeviceTypeCnName(deviceType.getCnName());
				}
				if (alertCounts == null) {
					alertCounts = typeCount(vo);
				}
			}

			res.setPageResult(result.getList());
			res.setTotalCount(result.getTotalCount());
			res.setPageNo(result.getPageNo());
			res.setPageSize(result.getPageSize());
			res.setAlertCounts(alertCounts);
		}

		return res;
	}

	public PageResult<SubhealthAirVo> pageAir(PageAirSubhealthMsg msg) {
		PageResult<SubhealthAirVo> res = this.infoDao.pageAir(msg.getPageNo(), msg.getPageSize(), SubhealthAirVo.class);
		for (SubhealthAirVo vo : res.getList()) {
			try {
				vo.setDatacenterName(this.assetService.detailDatacenter(vo.getDatacenterId(), null).getName());
			} catch (Exception e) {
				log.info("[SubhealthThresholdService][pageAir] AssetService的detailDatacenter方法访问异常: {}",
						e.getMessage());
			}
			try {
				vo.setAirHumidityIn(dataCleaningService.getAirHumidityIn(vo.getId()));
			} catch (Exception e) {
				log.info("[SubhealthThresholdService][pageAir] DataCleaningService的getAirCurrentTemp方法访问异常: {}",
						e.getMessage());
			}
			try {
				vo.setAirHumidityOut(dataCleaningService.getAirHumidityOut(vo.getId()));
			} catch (Exception e) {
				log.info("[SubhealthThresholdService][pageAir] DataCleaningService的getAirSetTemp方法访问异常: {}",
						e.getMessage());
			}
			try {
				vo.setAirOut(dataCleaningService.getAirOut(vo.getId()));
			} catch (Exception e) {
				log.info("[SubhealthThresholdService][pageAir] DataCleaningService的getAirOut方法访问异常: {}",
						e.getMessage());
			}
			try {
				vo.setAirIn(dataCleaningService.getAirIn(vo.getId()));
			} catch (Exception e) {
				log.info("[SubhealthThresholdService][pageAir] DataCleaningService的getAirIn方法访问异常: {}", e.getMessage());
			}
		}
		return res;
	}

	public PageResult<SubhealthUpsVo> pageUps(PageUpsSubhealthMsg msg) {

		ListDatacenterMsg listDatacenterMsg = new ListDatacenterMsg();
		Map<String, String> dcMap = assetService.listDatacenter(listDatacenterMsg).stream()
				.collect(Collectors.toMap(DatacenterItemVo::getId, s -> s.getName()));

		PageResult<SubhealthUpsVo> res = this.infoDao.pageUps(msg.getPageNo(), msg.getPageSize(), SubhealthUpsVo.class);
		ListDeviceMsg deviceMsg = new ListDeviceMsg();
		deviceMsg.setType(DeviceType.UPS.getNo());
		Map<String, DeviceItemVo> deviceMap = null;
		try {
			deviceMap = assetService.listDevice(deviceMsg).stream()
					.collect(Collectors.toMap(DeviceItemVo::getId, s -> s));
		} catch (Exception e) {
			log.info("[SubhealthThresholdService][pageUps] AssetService的listDevice方法访问异常: {}", e.getMessage());
		}
		if (deviceMap != null) {
			for (SubhealthUpsVo vo : res.getList()) {
				DeviceItemVo item = deviceMap.get(vo.getId());
				if (item != null) {
					vo.setDeviceModel(item.getDeviceModel());
				}
				try {
					vo.setUpsTemp(dataCleaningService.getUpsTemp(vo.getId()));
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][pageUps] DataCleaningService的getUpsTemp方法访问异常: {}",
							e.getMessage());
				}
				try {
					vo.setUpsVoltageIn(dataCleaningService.getUpsVoltageIn(vo.getId()));
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][pageUps] DataCleaningService的getUpsVoltageIn方法访问异常: {}",
							e.getMessage());
				}
				try {
					vo.setUpsVoltageOut(dataCleaningService.getUpsVoltageOut(vo.getId()));
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][pageUps] DataCleaningService的getUpsVoltageOut方法访问异常: {}",
							e.getMessage());
				}
				vo.setDatacenterName(dcMap.get(item.getDatacenterId()));
			}
		}

		return res;
	}

	public PageResult<SubhealthDatacenterVo> pageDatacenter(PageDatacenterSubhealthMsg msg) {
		PageResult<SubhealthDatacenterVo> datacenters = this.infoDao.pageDatacenter(msg.getPageNo(), msg.getPageSize(),
				SubhealthDatacenterVo.class);
		ListDatacenterMsg listDatacenterMsg = new ListDatacenterMsg();
		Map<String, DatacenterItemVo> datacenterMap = assetService.listDatacenter(listDatacenterMsg).stream()
				.collect(Collectors.toMap(DatacenterItemVo::getId, s -> s));
		ListDeviceMsg deviceMsg = new ListDeviceMsg();
		List<DeviceItemVo> devices = assetService.listDevice(deviceMsg);
		List<SubhealthInfoEntity> infos = infoDao.findAll();
		if (datacenters != null) {
			for (SubhealthDatacenterVo subhealthVo : datacenters.getList()) {
							
				DatacenterItemVo item = datacenterMap.get(subhealthVo.getId());
				if (item != null) {
					subhealthVo.setName(item.getName());
				}
				List<String> airs = devices.stream()
						.filter(s -> subhealthVo.getId().equals(s.getDatacenterId())
								&& DeviceType.AIR_CONDITION.equals(DeviceType.getDeviceTypeByNo(s.getType())))
						.map(s -> s.getId()).collect(Collectors.toList());
				int airCount = (int) infos.stream().filter(s -> airs.contains(s.getId()) && s.getSubhealth()).count();
				subhealthVo.setAirCount(airCount);
				List<String> ups = devices.stream()
						.filter(s -> subhealthVo.getId().equals(s.getDatacenterId())
								&& DeviceType.UPS.equals(DeviceType.getDeviceTypeByNo(s.getType())))
						.map(s -> s.getId()).collect(Collectors.toList());
				int upsCount = (int) infos.stream().filter(s -> ups.contains(s.getId()) && s.getSubhealth()).count();
				subhealthVo.setUpsCount(upsCount);
				
			}
		}
		return datacenters;
	}

	public List<SubhealthDatacenterVo> listDatacenter(ListDatacenterSubhealthMsg msg) {

		List<SubhealthDatacenterVo> res = new ArrayList<SubhealthDatacenterVo>();
		List<SubhealthInfoEntity> dcInfos = this.infoDao.findByProperty("device_type",
				SubhealthDeviceType.DATACENTER.getName());
		ListDatacenterMsg listDatacenterMsg = new ListDatacenterMsg();
		Map<String, DatacenterItemVo> datacenterMap = assetService.listDatacenter(listDatacenterMsg).stream()
				.collect(Collectors.toMap(DatacenterItemVo::getId, s -> s));

		ListDeviceMsg deviceMsg = new ListDeviceMsg();
		List<DeviceItemVo> devices = assetService.listDevice(deviceMsg);
		List<SubhealthInfoEntity> infos = infoDao.findAll();
		if (infos != null) {
			for (SubhealthInfoEntity dcInfo : dcInfos) {
				SubhealthDatacenterVo subhealthVo = new SubhealthDatacenterVo();
				subhealthVo.setId(dcInfo.getId());
				subhealthVo.setDeviceType(SubhealthDeviceType.DATACENTER.getName());
				subhealthVo.setSubhealth(dcInfo.getSubhealth());
				DatacenterItemVo item = datacenterMap.get(dcInfo.getId());
				if (item != null) {
					subhealthVo.setName(item.getName());
				}
				List<String> airs = devices.stream()
						.filter(s -> dcInfo.getId().equals(s.getDatacenterId())
								&& DeviceType.AIR_CONDITION.equals(DeviceType.getDeviceTypeByNo(s.getType())))
						.map(s -> s.getId()).collect(Collectors.toList());
				int airCount = (int) infos.stream().filter(s -> airs.contains(s.getId()) && s.getSubhealth()).count();
				subhealthVo.setAirCount(airCount);
				List<String> ups = devices.stream()
						.filter(s -> dcInfo.getId().equals(s.getDatacenterId())
								&& DeviceType.UPS.equals(DeviceType.getDeviceTypeByNo(s.getType())))
						.map(s -> s.getId()).collect(Collectors.toList());
				int upsCount = (int) infos.stream().filter(s -> ups.contains(s.getId()) && s.getSubhealth()).count();
				subhealthVo.setUpsCount(upsCount);
				res.add(subhealthVo);

			}
		}
		return res;
	}

	public List<ThresholdMeterVo> listThresholdMeter(ListThresholdMeterMsg msg) {
		if (msg.getType() != null) {
			SubhealthDeviceType type = SubhealthDeviceType.getByName(msg.getType());
			if (type == null) {
				throw new ParamException(AnalysisErrorCode.DEVICETYPE_NOT_FOUND);
			}
			return Stream.of(SubhealthThresholdMeter.values())
					.filter(s -> s.getType().getName().equals(msg.getType().toUpperCase())).map(s -> {
						if (s.getMeter() != null) {
							return new ThresholdMeterVo(s.getType().getName(), s.getName(), s.getCnName(),
									s.getMeter().getMeter());
						} else {
							return new ThresholdMeterVo(s.getType().getName(), s.getName(), s.getCnName(), s.getName());
						}
					}).collect(Collectors.toList());
		} else {
			return Stream.of(SubhealthThresholdMeter.values()).map(s -> {
				if (s.getMeter() != null) {
					return new ThresholdMeterVo(s.getType().getName(), s.getName(), s.getCnName(),
							s.getMeter().getMeter());
				} else {
					return new ThresholdMeterVo(s.getType().getName(), s.getName(), s.getCnName(), s.getName());
				}
			}).collect(Collectors.toList());
		}

	}

	public List<AlertLevelVo> listAlertLevel() {
		return Stream.of(SubhealthAlertLevelType.values()).map(s -> new AlertLevelVo(s.getName(), s.getCnName()))
				.collect(Collectors.toList());
	}

	public void setThreshold(SetSubhealthThresholdMsg msg) {

		checkMsg(msg);

		if (msg.getSubhealthThresholds() != null) {
			if (checkDuplicate(msg)) {
				throw new ParamException(AnalysisErrorCode.METER_DUPLICATE_ERROR);
			}
			for (SubhealthDeviceThresholdVo vo : msg.getSubhealthThresholds()) {
				SubhealthThresholdMeter meter = SubhealthThresholdMeter
						.getByMeterAndType(SubhealthDeviceType.getByName(vo.getType()), vo.getMeter());
				if (meter == null) {
					throw new ParamException(AnalysisErrorCode.METER_NOT_FOUND);
				}
				if (vo.getLevel() != null) {
					SubhealthAlertLevelType level = SubhealthAlertLevelType.getByName(vo.getLevel());
					if (level == null) {
						throw new ParamException(AnalysisErrorCode.LEVEL_NOT_FOUND);
					}
				}
				// thresholdSaveOrUpdate(vo);
				thresholdSaveOrUpdateByType(msg);

			}
			syncDelete(msg);

			updateCache();
		}
	}

	private void thresholdSaveOrUpdate(SubhealthDeviceThresholdVo vo) {
		Map<String, Object> props = new HashMap<String, Object>();
		// props.put("resource_id", vo.getResourceId());
		props.put("device_type", vo.getType());
		props.put("meter", vo.getMeter());
		SubhealthThresholdEntity threshold = tsDao.findUniqueByProperties(props);
		if (threshold == null) {
			threshold = new SubhealthThresholdEntity();
			threshold.setId(UUID.randomUUID().toString());
			threshold.setDeviceType(vo.getType());
			threshold.setLevel(vo.getLevel());
			threshold.setMeter(vo.getMeter());
			threshold.setMeterName(SubhealthThresholdMeter.getByMeter(vo.getMeter()).getCnName());
			threshold.setResourceId(vo.getResourceId());
			threshold.setLowerThreshold(vo.getLowerThreshold());
			threshold.setUpperThreshold(vo.getUpperThreshold());
			try {
				tsDao.save(threshold);
			} catch (Exception e) {
				log.info("[SubhealthThresholdService][thresholdSaveOrUpdate] 数据库保存失败: {}", e.getMessage());
			}

		} else {
			List<String> updates = new ArrayList<String>();
			if (vo.getLowerThreshold() != null && (threshold.getLowerThreshold() == null
					|| (float) threshold.getLowerThreshold() != (float) vo.getLowerThreshold())) {
				updates.add("lower_threshold");
				threshold.setLowerThreshold(vo.getLowerThreshold());
			}
			if (vo.getUpperThreshold() != null && (threshold.getLowerThreshold() == null
					|| (float) threshold.getUpperThreshold() != (float) vo.getUpperThreshold())) {
				updates.add("upper_threshold");
				threshold.setUpperThreshold(vo.getUpperThreshold());
			}
			if (vo.getLevel() != null && !threshold.getLevel().equals(vo.getLevel())) {
				updates.add("level");
				threshold.setLevel(vo.getLevel());
			}
			if (updates.size() > 0) {
				try {
					tsDao.update(threshold, updates);
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][thresholdSaveOrUpdate] 数据库更新失败: {}", e.getMessage());
				}
			}
		}
	}

	private void syncDelete(SetSubhealthThresholdMsg msg) {
		Map<String, Object> props = new HashMap<String, Object>();
		props.put("resource_id", msg.getResourceId());
		List<SubhealthThresholdEntity> exists = tsDao.findByProperties(props);
		Map<String, String> existMap = exists.stream()
				.collect(Collectors.toMap(SubhealthThresholdEntity::getMeter, SubhealthThresholdEntity::getId));
		List<String> nowMeters = msg.getSubhealthThresholds().stream().map(s -> s.getMeter())
				.collect(Collectors.toList());
		List<String> deletes = existMap.entrySet().stream().filter(s -> !nowMeters.contains(s.getKey()))
				.map(s -> s.getValue()).collect(Collectors.toList());
		for (String id : deletes) {
			try {
				tsDao.deleteById(id);
			} catch (Exception e) {
				log.info("[SubhealthThresholdService][thresholdSaveOrUpdate] 资源【{}】 数据库删除失败: {}", id, e.getMessage());
			}
		}
	}

	private boolean checkDuplicate(SetSubhealthThresholdMsg msg) {
		Map<String, Integer> meterMap = new HashMap<String, Integer>();
		for (SubhealthDeviceThresholdVo vo : msg.getSubhealthThresholds()) {
			Integer count = meterMap.getOrDefault(vo.getMeter(), 0);
			count = count + 1;
			meterMap.put(vo.getMeter(), count);
		}
		for (Entry<String, Integer> entry : meterMap.entrySet()) {
			if (entry.getValue() > 1) {
				return true;
			}
		}
		return false;
	}

	public List<SubhealthDeviceThresholdVo> listThreshold(ListSubhealthThresholdMsg msg) {
		List<SubhealthDeviceThresholdVo> result = tsDao.list(SubhealthDeviceThresholdVo.class);
		List<SubhealthDeviceThresholdVo> res = result.stream().filter(s -> {
			if (s.getType().equals(msg.getType())) {
				SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(s.getMeter());
				if (meter != null) {
					String unit = meter.getUnit();
					s.setUnit(unit);
				}
				return true;
			}
			return false;
		}).collect(Collectors.toList());

		return res;
	}

	private void checkDeviceSubhealth(SubhealthDeviceThresholdVo vo) {
		ListDeviceMsg deviceMsg = new ListDeviceMsg();
		SubhealthDeviceType type = SubhealthDeviceType.getByName(vo.getType());
		if (SubhealthDeviceType.AIR.equals(type)) {
			deviceMsg.setType(DeviceType.AIR_CONDITION.getNo());
		}
		if (SubhealthDeviceType.UPS.equals(type)) {
			deviceMsg.setType(DeviceType.UPS.getNo());
		}

		List<DeviceItemVo> devices = assetService.listDevice(deviceMsg);

		for (DeviceItemVo deviceItemVo : devices) {

			// 初始化设备亚健康
			SubhealthInfoEntity info = this.infoDao.getById(deviceItemVo.getId());
			if (info == null) {
				info = new SubhealthInfoEntity();
				info.setId(deviceItemVo.getId());
				info.setDeviceType(vo.getType());
				info.setSubhealth(false);
				try {
					this.infoDao.save(info);
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][checkDatacenterSubhealth] 数据库保存失败: {}", e.getMessage());
				}
			}

			double v = getMeterValue(vo.getMeter(), deviceItemVo.getId());
			// 判断上限阈值
			boolean upper = false;
			boolean lower = false;
			SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(vo.getMeter());
			if (vo.getUpperThreshold() != null && deviceItemVo != null && meter != null) {
				if (vo.getUpperThreshold() < v) {
					String content = "资源【" + deviceItemVo.getName() + "】" + meter.getCnName() + "【"
							+ MeshMathUtil.setScale(v, "0.00") + "】" + "超过上限阈值"
							+ MeshMathUtil.setScale(vo.getUpperThreshold(), "0.00");
					updateSubhealthStatus(vo, deviceItemVo.getId());
					saveAlert(vo, deviceItemVo.getId(), deviceItemVo.getName(), content, vo.getLevel());
				} else {
					upper = true;
				}
			}
			// 判断下限阈值
			if (vo.getLowerThreshold() != null && deviceItemVo != null && meter != null) {
				if (vo.getLowerThreshold() > v) {
					String content = "资源【" + deviceItemVo.getName() + "】" + meter.getCnName() + "【"
							+ MeshMathUtil.setScale(v, "0.00") + "】" + "低于下限阈值"
							+ MeshMathUtil.setScale(vo.getLowerThreshold(), "0.00");
					updateSubhealthStatus(vo, deviceItemVo.getId());
					saveAlert(vo, deviceItemVo.getId(), deviceItemVo.getName(), content, vo.getLevel());
				} else {
					lower = true;
				}
			}
			if (upper && lower) {
				updateSubhealthStatus(deviceItemVo.getId(), false);
			}
		}

	}

	private void checkDeviceSubhealth(SubhealthDeviceType type, List<SubhealthDeviceThresholdVo> thresholds) {
		ListDeviceMsg deviceMsg = new ListDeviceMsg();
		if (SubhealthDeviceType.AIR.equals(type)) {
			deviceMsg.setType(DeviceType.AIR_CONDITION.getNo());
		}
		if (SubhealthDeviceType.UPS.equals(type)) {
			deviceMsg.setType(DeviceType.UPS.getNo());
		}

		List<DeviceItemVo> devices = assetService.listDevice(deviceMsg);

		for (DeviceItemVo deviceItemVo : devices) {

			// 初始化设备亚健康
			SubhealthInfoEntity info = this.infoDao.getById(deviceItemVo.getId());
			if (info == null) {
				info = new SubhealthInfoEntity();
				info.setId(deviceItemVo.getId());
				info.setDeviceType(type.getName());
				info.setSubhealth(false);
				try {
					this.infoDao.save(info);
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][checkDatacenterSubhealth] 数据库保存失败: {}", e.getMessage());
				}
			}

			// 判断上限阈值
			boolean airInTempUpper = false;
			boolean airInTempLower = false;
			boolean airOutTempUpper = false;
			boolean airOutTempLower = false;
			boolean airInHumidityUpper = false;
			boolean airInHumidityLower = false;
			boolean airOutHumidityUpper = false;
			boolean airOutHumidityLower = false;
			boolean upsInVoltageUpper = false;
			boolean upsInVoltageLower = false;
			boolean upsOutVoltageUpper = false;
			boolean upsOutVoltageLower = false;
			boolean upsTempUpper = false;
			boolean upsTempLower = false;

			for (SubhealthDeviceThresholdVo vo : thresholds) {
				SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(vo.getMeter());
				double v = getMeterValue(vo.getMeter(), deviceItemVo.getId());
				if (vo.getUpperThreshold() != null && deviceItemVo != null && meter != null) {
					if (vo.getUpperThreshold() < v) {
						String content = "资源【" + deviceItemVo.getName() + "】" + meter.getCnName() + "【"
								+ MeshMathUtil.setScale(v, "0.00") + "】" + "超过上限阈值"
								+ MeshMathUtil.setScale(vo.getUpperThreshold(), "0.00");
						updateSubhealthStatus(vo, deviceItemVo.getId());
						saveAlert(vo, deviceItemVo.getId(), deviceItemVo.getName(), content, vo.getLevel());
					} else if (SubhealthThresholdMeter.AIR_IN_TEMPERATURE.equals(meter)) {
						airInTempUpper = true;
					} else if (SubhealthThresholdMeter.AIR_OUT_TEMPERATURE.equals(meter)) {
						airOutTempUpper = true;
					} else if (SubhealthThresholdMeter.AIR_IN_HUMIDITY.equals(meter)) {
						airInHumidityUpper = true;
					} else if (SubhealthThresholdMeter.AIR_OUT_HUMIDITY.equals(meter)) {
						airOutHumidityUpper = true;
					} else if (SubhealthThresholdMeter.UPS_IN_VOLTAGE.equals(meter)) {
						upsInVoltageUpper = true;
					} else if (SubhealthThresholdMeter.UPS_OUT_VOLTAGE.equals(meter)) {
						upsOutVoltageUpper = true;
					} else if (SubhealthThresholdMeter.UPS_TEMPERATURE.equals(meter)) {
						upsTempUpper = true;
					}
				}
				// 判断下限阈值
				if (vo.getLowerThreshold() != null && deviceItemVo != null && meter != null) {
					if (vo.getLowerThreshold() > v) {
						String content = "资源【" + deviceItemVo.getName() + "】" + meter.getCnName() + "【"
								+ MeshMathUtil.setScale(v, "0.00") + "】" + "低于下限阈值"
								+ MeshMathUtil.setScale(vo.getLowerThreshold(), "0.00");
						updateSubhealthStatus(vo, deviceItemVo.getId());
						saveAlert(vo, deviceItemVo.getId(), deviceItemVo.getName(), content, vo.getLevel());
					} else if (SubhealthThresholdMeter.AIR_IN_TEMPERATURE.equals(meter)) {
						airInTempLower = true;
					} else if (SubhealthThresholdMeter.AIR_OUT_TEMPERATURE.equals(meter)) {
						airOutTempLower = true;
					} else if (SubhealthThresholdMeter.AIR_IN_HUMIDITY.equals(meter)) {
						airInHumidityLower = true;
					} else if (SubhealthThresholdMeter.AIR_OUT_HUMIDITY.equals(meter)) {
						airOutHumidityLower = true;
					} else if (SubhealthThresholdMeter.UPS_IN_VOLTAGE.equals(meter)) {
						upsInVoltageLower = true;
					} else if (SubhealthThresholdMeter.UPS_OUT_VOLTAGE.equals(meter)) {
						upsOutVoltageLower = true;
					} else if (SubhealthThresholdMeter.UPS_TEMPERATURE.equals(meter)) {
						upsTempLower = true;
					}
				}

			}
			if (SubhealthDeviceType.AIR.equals(type) && airInTempUpper && airInTempLower && airOutTempUpper
					&& airOutTempLower && airInHumidityUpper && airInHumidityLower && airOutHumidityUpper
					&& airOutHumidityLower) {
				updateSubhealthStatus(deviceItemVo.getId(), false);
			}
			if (SubhealthDeviceType.UPS.equals(type) && upsInVoltageUpper && upsInVoltageLower && upsOutVoltageUpper
					&& upsOutVoltageLower && upsTempUpper && upsTempLower) {
				updateSubhealthStatus(deviceItemVo.getId(), false);
			}

		}

	}

	private void checkDatacenterSubhealth(SubhealthDeviceThresholdVo vo) {
		ListDatacenterMsg dcMsg = new ListDatacenterMsg();
		List<DatacenterItemVo> datacenters = assetService.listDatacenter(dcMsg);
		ListDeviceMsg deviceMsg = new ListDeviceMsg();
		List<DeviceItemVo> devices = assetService.listDevice(deviceMsg);

		for (DatacenterItemVo dcItemVo : datacenters) {

			// 初始化数据中心亚健康
			SubhealthInfoEntity info = this.infoDao.getById(dcItemVo.getId());
			if (info == null) {
				info = new SubhealthInfoEntity();
				info.setId(dcItemVo.getId());
				info.setDeviceType(vo.getType());
				info.setSubhealth(false);
				try {
					this.infoDao.save(info);
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][checkDatacenterSubhealth] 数据库保存失败: {}", e.getMessage());
				}
			}

			SubhealthThresholdMeter type = SubhealthThresholdMeter.getByName(vo.getMeter());
			int v = checkDatacenterSubhealth(vo, type, devices, dcItemVo.getId());
			// 判断上限阈值
			SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(vo.getMeter());
			if (vo.getUpperThreshold() != null && dcItemVo != null && meter != null) {
				if (vo.getUpperThreshold() < v) {
					String content = "资源【" + dcItemVo.getName() + "】" + meter.getCnName() + "【" + v + "】" + "超过阈值"
							+ (int) vo.getUpperThreshold().floatValue();
					updateSubhealthStatus(vo, dcItemVo.getId());
					saveAlert(vo, dcItemVo.getId(), dcItemVo.getName(), content, vo.getLevel());
				} else {
					updateSubhealthStatus(dcItemVo.getId(), false);
				}
			}
			// 判断下限阈值
			// if (vo.getLowerThreshold() != null && dcItemVo != null && meter
			// != null) {
			// if (vo.getLowerThreshold() > v) {
			// String content = "资源【" + dcItemVo.getName() + "】" +
			// meter.getCnName() + "【" + v + "】" + "低于下限阈值" +
			// (int)vo.getLowerThreshold().floatValue();
			// updateSubhealthStatus(vo, dcItemVo.getId());
			// saveAlert(vo, dcItemVo.getId(), dcItemVo.getName(), content);
			// }
			// }
		}

	}

	private void checkDatacenterSubhealth(SubhealthDeviceType type, List<SubhealthDeviceThresholdVo> thresholds) {
		ListDatacenterMsg dcMsg = new ListDatacenterMsg();
		List<DatacenterItemVo> datacenters = assetService.listDatacenter(dcMsg);
		ListDeviceMsg deviceMsg = new ListDeviceMsg();
		List<DeviceItemVo> devices = assetService.listDevice(deviceMsg);

		for (DatacenterItemVo dcItemVo : datacenters) {

			// 初始化数据中心亚健康
			SubhealthInfoEntity info = this.infoDao.getById(dcItemVo.getId());
			if (info == null) {
				info = new SubhealthInfoEntity();
				info.setId(dcItemVo.getId());
				info.setDeviceType(type.getName());
				info.setSubhealth(false);
				try {
					this.infoDao.save(info);
				} catch (Exception e) {
					log.info("[SubhealthThresholdService][checkDatacenterSubhealth] 数据库保存失败: {}", e.getMessage());
				}
			}
			boolean upsUpper = false;
			boolean airUpper = false;
			for (SubhealthDeviceThresholdVo vo : thresholds) {
				SubhealthThresholdMeter meterType = SubhealthThresholdMeter.getByName(vo.getMeter());
				int v = checkDatacenterSubhealth(vo, meterType, devices, dcItemVo.getId());
				// 判断上限阈值
				SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(vo.getMeter());
				if (vo.getUpperThreshold() != null && dcItemVo != null && meter != null) {
					if (vo.getUpperThreshold() < v) {
						String content = "资源【" + dcItemVo.getName() + "】" + meter.getCnName() + "【" + v + "】" + "超过阈值"
								+ (int) vo.getUpperThreshold().floatValue();
						updateSubhealthStatus(vo, dcItemVo.getId());
						saveAlert(vo, dcItemVo.getId(), dcItemVo.getName(), content, vo.getLevel());
						continue;
					} else if (SubhealthThresholdMeter.DATACENTER_UPS.equals(meter)) {
						upsUpper = true;
					} else if (SubhealthThresholdMeter.DATACENTER_AIR.equals(meter)) {
						airUpper = true;
					}
				}
			}
			if (upsUpper && airUpper) {
				updateSubhealthStatus(dcItemVo.getId(), false);
			}
			// else {
			// updateSubhealthStatus(dcItemVo.getId(), true);
			// }
		}

	}

	// private int checkDatacenterSubhealth(SubhealthDeviceThresholdVo vo,
	// String type, boolean subhealth) {
	//
	//
	//
	// ListDeviceMsg msg = new ListDeviceMsg();
	// msg.setDatacenterId(vo.getResourceId());
	// List<String> deviceIds = null;
	// try {
	// deviceIds = assetService.listDevice(msg).stream().map(s ->
	// s.getId()).collect(Collectors.toList());
	// } catch (Exception e) {
	// log.info("[SubhealthThresholdService][checkDatacenterSubhealth]
	// checkDatacenterSubhealth执行失败, AssetService的listDevice方法访问异常: {}",
	// e.getMessage());
	// }
	// if (deviceIds != null) {
	// Map<String, Object> props = new HashMap<String, Object>();
	// props.put("device_type", type.toUpperCase());
	// props.put("subhealth", subhealth);
	// // List<SubhealthInfoEntity> subhealthInfos =
	// // infoDao.findByProperties(props).stream()
	// // .filter( s -> deviceIds.contains(s.getId()))
	// // .collect(Collectors.toList());
	// List<String> subhealthInfos =
	// infoDao.findByProperties(props).stream().map(s ->
	// s.getId()).collect(Collectors.toList());
	// subhealthInfos.retainAll(deviceIds);
	// return subhealthInfos.size();
	// }
	// return 0;
	// }

	private int checkDatacenterSubhealth(SubhealthDeviceThresholdVo vo, SubhealthThresholdMeter type,
			List<DeviceItemVo> devices, String datacenterId) {

		List<SubhealthInfoEntity> infos = infoDao.findAll();
		if (infos != null) {
			if (SubhealthThresholdMeter.DATACENTER_AIR.equals(type)) {
				List<String> airs = devices.stream()
						.filter(s -> s.getDatacenterId().equals(datacenterId)
								&& DeviceType.AIR_CONDITION.equals(DeviceType.getDeviceTypeByNo(s.getType())))
						.map(s -> s.getId()).collect(Collectors.toList());
				int airCount = (int) infos.stream().filter(s -> airs.contains(s.getId()) && s.getSubhealth()).count();
				return airCount;
			}
			if (SubhealthThresholdMeter.DATACENTER_UPS.equals(type)) {
				List<String> ups = devices.stream()
						.filter(s -> s.getDatacenterId().equals(datacenterId)
								&& DeviceType.UPS.equals(DeviceType.getDeviceTypeByNo(s.getType())))
						.map(s -> s.getId()).collect(Collectors.toList());
				int upsCount = (int) infos.stream().filter(s -> ups.contains(s.getId()) && s.getSubhealth()).count();
				return upsCount;
			}

		}
		return 0;
	}

	// 按类型设置阈值
	private void thresholdSaveOrUpdateByType(SetSubhealthThresholdMsg msg) {

		msg.getSubhealthThresholds().forEach(s -> thresholdSaveOrUpdate(s));

	}

	private boolean checkMsg(SetSubhealthThresholdMsg msg) {
		if (msg.getSubhealthThresholds() != null) {
			for (SubhealthDeviceThresholdVo vo : msg.getSubhealthThresholds()) {
				// 上下限阈值合理性校验，下限阈值应 <= 上限阈值
				if (vo.getUpperThreshold() != null && vo.getLowerThreshold() != null
						&& vo.getLowerThreshold() > vo.getUpperThreshold()) {
					throw new BaseException(SubhealthErrorCode.THRESHOLD_UPPER_LOWER_ERROR);
				}
				SubhealthThresholdMeter meter = SubhealthThresholdMeter.getByMeter(vo.getMeter());
				if (meter == null) {
					throw new ParamException(AnalysisErrorCode.METER_NOT_FOUND);
				}

				if (meter.equals(SubhealthThresholdMeter.AIR_IN_HUMIDITY)
						|| meter.equals(SubhealthThresholdMeter.AIR_OUT_HUMIDITY)) {
					// 最小值：0，最大值：100
					if (vo.getLowerThreshold() != null) {
						checkFloat(vo.getLowerThreshold().toString());
						if (vo.getLowerThreshold() < 0) {
							throw new ParamException(null, "空调出风/回风湿度取值范围0~100");
						}
					}
					if (vo.getUpperThreshold() != null) {
						checkFloat(vo.getUpperThreshold().toString());
						if (vo.getUpperThreshold() > 100) {
							throw new ParamException(null, "空调出风/回风湿度取值范围0~100");
						}
					}
				}
				if (meter.equals(SubhealthThresholdMeter.AIR_IN_TEMPERATURE)
						|| meter.equals(SubhealthThresholdMeter.AIR_OUT_TEMPERATURE)
						|| meter.equals(SubhealthThresholdMeter.UPS_TEMPERATURE)) {
					// 最低温度：0.01，最高温度设定为：100
					if (vo.getLowerThreshold() != null) {
						checkFloat(vo.getLowerThreshold().toString());
						if (vo.getLowerThreshold() < 0.01) {
							if (meter.equals(SubhealthThresholdMeter.UPS_TEMPERATURE)) {
								throw new ParamException(null, "UPS温度取值范围0.01~100");
							} else {
								throw new ParamException(null, "空调出风/回风温度取值范围0.01~100");
							}

						}
					}
					if (vo.getUpperThreshold() != null) {
						checkFloat(vo.getUpperThreshold().toString());
						if (vo.getUpperThreshold() > 100) {
							if (meter.equals(SubhealthThresholdMeter.UPS_TEMPERATURE)) {
								throw new ParamException(null, "UPS温度取值范围0.01~100");
							} else {
								throw new ParamException(null, "空调出风/回风温度取值范围0.01~100");
							}
						}
					}
				}
				if (meter.equals(SubhealthThresholdMeter.UPS_IN_VOLTAGE)
						|| meter.equals(SubhealthThresholdMeter.UPS_OUT_VOLTAGE)) {
					// 最小值：0，最大值设为：500
					if (vo.getLowerThreshold() != null) {
						checkFloat(vo.getLowerThreshold().toString());
						if (vo.getLowerThreshold() < 0) {
							throw new ParamException(null, "UPS输入/输出电压取值范围0~500");
						}
					}
					if (vo.getUpperThreshold() != null) {
						checkFloat(vo.getUpperThreshold().toString());
						if (vo.getUpperThreshold() > 500) {
							throw new ParamException(null, "UPS输入/输出电压取值范围0~500");
						}
					}
				}
				// if(meter.equals(SubhealthThresholdMeter.UPS_TEMPERATURE)) {
				// // 最低温度设定为：0，最高温度设定为：150
				// if(vo.getLowerThreshold() != null) {
				// checkFloat(vo.getLowerThreshold().toString());
				// if(vo.getLowerThreshold() < 0) {
				// throw new
				// BaseException(SubhealthErrorCode.UPS_TEMPERATURE_DATA_ERROR);
				// }
				// }
				// if(vo.getUpperThreshold() != null) {
				// checkFloat(vo.getUpperThreshold().toString());
				// if(vo.getUpperThreshold() > 150) {
				// throw new
				// BaseException(SubhealthErrorCode.UPS_TEMPERATURE_DATA_ERROR);
				// }
				// }
				// }
				if (meter.equals(SubhealthThresholdMeter.DATACENTER_AIR)
						|| meter.equals(SubhealthThresholdMeter.DATACENTER_UPS)) {
					// 正整数 0 ~ 99999
					if (vo.getLowerThreshold() != null) {
						checkInt(vo.getLowerThreshold().toString());
						if (vo.getLowerThreshold() < 0) {
							if (meter.equals(SubhealthThresholdMeter.DATACENTER_AIR)) {
								throw new ParamException(null, "AIR取值范围0~99999");
							} else {
								throw new ParamException(null, "UPS取值范围0~99999");
							}

						}
					}
					if (vo.getUpperThreshold() != null) {
						checkInt(vo.getUpperThreshold().toString());
						if (vo.getUpperThreshold() > 99999) {
							if (meter.equals(SubhealthThresholdMeter.DATACENTER_AIR)) {
								throw new ParamException(null, "AIR取值范围0~99999");
							} else {
								throw new ParamException(null, "UPS取值范围0~99999");
							}
						}
					}
				}

			}
		}
		return true;
	}

	private int checkInt(String s) {
		int res = 0;
		try {
			int index = s.indexOf('.');
			String value = s.substring(index + 1, s.length());
			System.out.println(value);
			int v = Integer.valueOf(value);
			res = v;
		} catch (Exception e) {
			throw new BaseException(SubhealthErrorCode.DATA_TYPE_ERROR);
		}
		if (res != 0) {
			throw new BaseException(null, "请输入正整数");
		}
		return res;
	}

	private float checkFloat(String s) {
		if (s.length() > 10) {
			throw new BaseException(SubhealthErrorCode.DATACENTER_DATA_LENGTH_ERROR);
		}
		float res;
		try {
			res = Float.valueOf(s);
		} catch (Exception e) {
			throw new BaseException(SubhealthErrorCode.DATA_TYPE_ERROR);
		}
		return res;
	}

	private void initSubhealthThreshold() {
		List<SubhealthThresholdMeter> meters = Stream.of(SubhealthThresholdMeter.values()).collect(Collectors.toList());

		for (SubhealthThresholdMeter meter : meters) {
			if (meter.equals(SubhealthThresholdMeter.AIR_IN_HUMIDITY)
					|| meter.equals(SubhealthThresholdMeter.AIR_OUT_HUMIDITY)) {
				// 最小值：0，最大值：100
				saveThreshold(SubhealthDeviceType.AIR.getName(), meter.getMeter().getMeter(), meter.getCnName(),
						SubhealthAlertLevelType.INFO.getName(), 20f, 50f);
			}
			if (meter.equals(SubhealthThresholdMeter.AIR_IN_TEMPERATURE)
					|| meter.equals(SubhealthThresholdMeter.AIR_OUT_TEMPERATURE)) {
				// 最低温度：0.01，最高温度设定为：100
				saveThreshold(SubhealthDeviceType.AIR.getName(), meter.getMeter().getMeter(), meter.getCnName(),
						SubhealthAlertLevelType.INFO.getName(), 20f, 60f);
			}
			if (meter.equals(SubhealthThresholdMeter.UPS_TEMPERATURE)) {
				// 最低温度：0.01，最高温度设定为：100
				saveThreshold(SubhealthDeviceType.UPS.getName(), meter.getMeter().getMeter(), meter.getCnName(),
						SubhealthAlertLevelType.INFO.getName(), 20f, 60f);
			}
			if (meter.equals(SubhealthThresholdMeter.UPS_IN_VOLTAGE)
					|| meter.equals(SubhealthThresholdMeter.UPS_OUT_VOLTAGE)) {
				// 最小值：0，最大值设为：99999
				saveThreshold(SubhealthDeviceType.UPS.getName(), meter.getMeter().getMeter(), meter.getCnName(),
						SubhealthAlertLevelType.INFO.getName(), 100f, 200f);
			}

			if (meter.equals(SubhealthThresholdMeter.DATACENTER_AIR)
					|| meter.equals(SubhealthThresholdMeter.DATACENTER_UPS)) {
				// 正整数 0 ~ 99999
				saveThreshold(SubhealthDeviceType.DATACENTER.getName(), meter.getName(), meter.getCnName(),
						SubhealthAlertLevelType.INFO.getName(), null, 10f);
			}
		}
	}

	private void saveThreshold(String type, String meter, String meterName, String level, Float lowerThreshold,
			Float upperThreshold) {

		Map<String, Object> props = new HashMap<String, Object>();
		props.put("device_type", type);
		props.put("meter", meter);

		SubhealthThresholdEntity threshold = tsDao.findUniqueByProperties(props);
		if (threshold == null) {
			threshold = new SubhealthThresholdEntity();
			threshold.setId(UUID.randomUUID().toString());
			threshold.setDeviceType(type);
			threshold.setResourceId(UUID.randomUUID().toString());
			threshold.setLevel(level);
			threshold.setMeter(meter);
			threshold.setMeterName(meterName);
			threshold.setLowerThreshold(lowerThreshold);
			threshold.setUpperThreshold(upperThreshold);
			tsDao.save(threshold);
		}
	}

	private List<AlertStatisticVo> typeCount(SubhealthAlertVo vo) {
		List<AlertStatisticVo> alertCounts = new ArrayList<AlertStatisticVo>();
		if (StringUtils.isNotBlank(vo.getTypeCount())) {
			try {
				Map<String, Integer> countMap = new HashMap<String, Integer>();
				countMap.put(SubhealthDeviceType.AIR.getName(), 0);
				countMap.put(SubhealthDeviceType.UPS.getName(), 0);
				countMap.put(SubhealthDeviceType.DATACENTER.getName(), 0);
				String[] types = vo.getTypeCount().split(",");
				for (String type : types) {
					String[] kv = type.split(":");
					if (kv.length == 2) {
						String k = kv[0].trim();
						countMap.put(k, Integer.valueOf(kv[1]));
					}
				}
				for (Entry<String, Integer> entry : countMap.entrySet()) {
					AlertStatisticVo alert = new AlertStatisticVo();
					alert.setType(entry.getKey());
					alert.setValue(entry.getValue());
					SubhealthDeviceType deviceType = SubhealthDeviceType.getByName(entry.getKey());
					if (deviceType != null) {
						alert.setName(deviceType.getCnName() + TEMPLATE);
					}
					alertCounts.add(alert);
				}
			} catch (Exception e) {
				log.error("[SubhealthThresholdService][typeCount] 数据库按类型分组统计解析失败: {}", e.getMessage());
			}

		}
		return alertCounts;
	}

	private void updateSubhealthStatus(String resourceId, boolean status) {

		SubhealthInfoEntity e = this.infoDao.getById(resourceId);
		if (e != null) {
			e.setSubhealth(status);
			try {
				this.infoDao.update(e);
			} catch (Exception ee) {
				log.error("[SubhealthThresholdService][updateSubhealthStatus] 数据库按类型分组统计解析失败: {}", ee.getMessage());
			}

		}
	}
	
	private double predictTimeSeries(Double value) {
		double res = 0;
//		res = value.doubleValue();
		res = arimaManager.predict(value);
		return res;
	}
}
